/*
 * Based on
 * stats.js r5
 * http://github.com/mrdoob/stats.js
 *
 * Released under MIT license:
 * http://www.opensource.org/licenses/mit-license.php
 *
 * Modifications:
 * - removed the mem graph
 * - inject fps instead of computing it
 * - make it possible to insert more than 1 fps measurement
 *
 *  var stats = new Stats();
 *  parentElement.appendChild( stats.domElement );
 *
 *  setInterval(function () {
 *
 *  	stats.update(nextFps);
 *
 *  }, 1000/60);
 *
 */

var Stats = function () {

	var _mode = 0, _modesCount = 2, _container,
	_fpsMin = 1000, _fpsMax = 0, _fpsDiv, _fpsText, _fpsCanvas, _fpsContext, _fpsImageData,
	_msMin = 1000, _msMax = 0, _msDiv, _msText, _msCanvas, _msContext, _msImageData,
        _containerWidth = 778, _canvasWidth = _containerWidth - 6, _canvasHeight = 197,
        _fontSize = '12px',
	_colors = {
		fps: {
			bg: { r: 240, g: 240, b: 240 },
			fg: { r: 0, g: 102, b: 204 }
		},
		ms: {
			bg: { r: 240, g: 240, b: 240 },
			fg: { r: 0, g: 138, b: 53 }
		},
	};

	_container = document.createElement( 'div' );
	_container.style.cursor = 'pointer';
	_container.style.width = _containerWidth + 'px';
	_container.style.opacity = '0.9';
	_container.style.zIndex = '10001';
	_container.addEventListener( 'click', swapMode, false );

	// fps

	_fpsDiv = document.createElement( 'div' );
	_fpsDiv.style.padding = '2px 0px 3px 0px';
	_container.appendChild( _fpsDiv );

	_fpsText = document.createElement( 'div' );
	_fpsText.style.textAlign = 'left';
	_fpsText.style.color = 'rgb(' + _colors.fps.fg.r + ',' + _colors.fps.fg.g + ',' + _colors.fps.fg.b + ')';
	_fpsText.style.margin = '0px 0px 1px 3px';
	_fpsText.innerHTML = '<span style="font-weight:bold">FPS</span>';
	_fpsDiv.appendChild( _fpsText );

	_fpsCanvas = document.createElement( 'canvas' );
	_fpsCanvas.width = _canvasWidth;
	_fpsCanvas.height = _canvasHeight;
	_fpsCanvas.style.display = 'block';
	_fpsCanvas.style.marginLeft = '3px';
	_fpsDiv.appendChild( _fpsCanvas );

	_fpsContext = _fpsCanvas.getContext( '2d' );
	_fpsContext.fillStyle = 'rgb(' + _colors.fps.bg.r + ',' + _colors.fps.bg.g + ',' + _colors.fps.bg.b + ')';
	_fpsContext.fillRect( 0, 0, _fpsCanvas.width, _fpsCanvas.height );

	_fpsImageData = _fpsContext.getImageData( 0, 0, _fpsCanvas.width, _fpsCanvas.height );

	// ms

	_msDiv = document.createElement( 'div' );
	_msDiv.style.padding = '2px 0px 3px 0px';
	_msDiv.style.display = 'none';
	_container.appendChild( _msDiv );

	_msText = document.createElement( 'div' );
	_msText.style.textAlign = 'left';
	_msText.style.color = 'rgb(' + _colors.ms.fg.r + ',' + _colors.ms.fg.g + ',' + _colors.ms.fg.b + ')';
	_msText.style.margin = '0px 0px 1px 3px';
	_msText.innerHTML = '<span style="font-weight:bold">ms</span>';
	_msDiv.appendChild( _msText );

	_msCanvas = document.createElement( 'canvas' );
	_msCanvas.width = _canvasWidth;
	_msCanvas.height = _canvasHeight;
	_msCanvas.style.display = 'block';
	_msCanvas.style.marginLeft = '3px';
	_msDiv.appendChild( _msCanvas );

	_msContext = _msCanvas.getContext( '2d' );
	_msContext.fillStyle = 'rgb(' + _colors.ms.bg.r + ',' + _colors.ms.bg.g + ',' + _colors.ms.bg.b + ')';
	_msContext.fillRect( 0, 0, _msCanvas.width, _msCanvas.height );

	_msImageData = _msContext.getImageData( 0, 0, _msCanvas.width, _msCanvas.height );

	function updateGraph( data, value, color ) {

		var x, y, index, i;

                var l = value.length;

		for ( y = 0; y < _canvasHeight; y++ ) {

			for ( x = 0; x < _canvasWidth - l; x++ ) {

				index = (x + y * _canvasWidth) * 4;

				data[ index ] = data[ index + l * 4 ];
				data[ index + 1 ] = data[ index + l * 4 + 1 ];
				data[ index + 2 ] = data[ index + l * 4 + 2 ];

			}

		}

		for ( y = 0; y < _canvasHeight; y++ ) {

			for ( x = _canvasWidth - l, i = 0; x < _canvasWidth; x++, i++ ) {

				index = (x + y * _canvasWidth) * 4;

                                if ( y < value[i] ) {

                                        data[ index ] = _colors[ color ].bg.r;
                                        data[ index + 1 ] = _colors[ color ].bg.g;
                                        data[ index + 2 ] = _colors[ color ].bg.b;

                                } else {

                                        data[ index ] = _colors[ color ].fg.r;
                                        data[ index + 1 ] = _colors[ color ].fg.g;
                                        data[ index + 2 ] = _colors[ color ].fg.b;

                                }

                        }

		}

	}

	function swapMode() {

		_mode ++;
		_mode == _modesCount ? _mode = 0 : _mode;

		_fpsDiv.style.display = 'none';
		_msDiv.style.display = 'none';

		switch( _mode ) {

			case 0:

				_fpsDiv.style.display = 'block';

				break;

			case 1:

				_msDiv.style.display = 'block';

				break;
		}

	}

        function str(n) {
          return Math.round(10*n) / 10;  // 9_9
        }

	return {

		domElement: _container,

		update: function (fps) {
                        // Normally, you wouldn't want to print fps every single frame.

                        if (fps.length > _canvasWidth)
                          fps = fps.slice(fps.length - _canvasWidth);

                        var ms = [];
                        for (var i = 0; i < fps.length; ++i) {
                                fps[i] = parseFloat(fps[i]);
                                ms.push(1000 / fps[i]);
                        }

			_msText.innerHTML = '<span style="font-weight:bold">' + str(ms[ms.length - 1]) + ' ms</span>';

                        for (var i = 0; i < ms.length; ++i) {
                                _msMin = Math.min( _msMin, ms[i] );
                                _msMax = Math.max( _msMax, ms[i] );
                                ms[i] = Math.min( _canvasHeight, _canvasHeight * (1 - ms[i] / 100) );
                        }
			updateGraph( _msImageData.data, ms, 'ms' );
			_msContext.putImageData( _msImageData, 0, 0 );


                        _fpsText.innerHTML = '<span style="font-weight:bold">' + str(fps[fps.length - 1]) + ' FPS</span>';

                        for (var i = 0; i < fps.length; ++i) {
                                _fpsMin = Math.min( _fpsMin, fps[i] );
                                _fpsMax = Math.max( _fpsMax, fps[i] );
                                fps[i] = Math.min( _canvasHeight, _canvasHeight * (1 - fps[i] / 100) );
                        }
                        updateGraph( _fpsImageData.data, fps, 'fps' );
                        _fpsContext.putImageData( _fpsImageData, 0, 0 );
		}

	};

};
